package edu.mercer.sse.ldap;

import edu.mercer.sse.app.Config;

import java.security.GeneralSecurityException;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Map;

import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.unboundid.ldap.sdk.LDAPException;

import edu.mercer.sse.database.DB2LDAPLayout;
import edu.mercer.sse.errors.CriticalException;
import edu.mercer.sse.errors.ErrorLoggingVisitor;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Show Database entries to be added to LDAP.<p>
 * 
 * Report which Database entries are not present in LDAP, as in database->LDAP 
 * 	layout data synchronization/publishing.<p>
 *
 * @see Predicate
 */

public class LDAPAddPredicate implements 

		Predicate<Map<String,String>>
{
	/** 
	 * Show Database entries to be added to LDAP.<p>
	 * 
	 * No-arg constructor.<p>
	 * 
	 * Report which Database entries are not present in LDAP, as in 
	 * 	database->LDAP layout data synchronization/publishing.<p>
	 *
	 * @see Predicate  
	 */
	
	public LDAPAddPredicate(){}
	
	
	@Override
	public boolean apply( final Map<String, String> databaseEntry )
	{
		try
		{
			checkNotNull( databaseEntry, "null database entry, expect " + 
					"ImmutableMap<String, String>" );

			checkArgument( databaseEntry.size() > 0, "empty ImmutableMap " +
					"database entry" );
									
			final ImmutableList<ImmutableMap<String,String>> ldapEntries = 
					LDAPOrgUnit.getList();

			final String uidKey = Config.settings().getProperty(
					"ldap-member-id");

			checkArgument( ldapEntries.size() > 0, "zero LDAP OU entries " + 
					"retrieved" );
			
			checkArgument( ldapEntries.get(0).containsKey( uidKey ), uidKey 
					+ " missing in ldap 1st entry " + ldapEntries.get(0) );
			
			String userIDfromDB = "";
			
			if( databaseEntry.containsKey( uidKey ) )
			{ 		
				userIDfromDB = databaseEntry.get( uidKey );
			
			}
			else
			{
				/* 
				 * uid missing, seek query columns instead of ldap keys 
				 */
				
				final String uidQryColumn = DB2LDAPLayout
						.getLayout()
						.inverse()
						.get( uidKey );
				
				checkArgument( databaseEntry.containsKey( uidQryColumn ), 
						"missing " 
						+ uidKey 
						+ " and " 
						+ uidQryColumn );
			
				userIDfromDB = databaseEntry.get( uidQryColumn );
				
			}//if
				
			checkArgument( userIDfromDB.length() > 0, "empty: " + uidKey 
					+ " in entry from database" );

			final Iterator<ImmutableMap<String,String>> ldapRecs = 
					ldapEntries.iterator(); 
			
			checkArgument( ldapRecs.hasNext(), "fail to iterate ldap" 
					+ " entries" );
			
			while( ldapRecs.hasNext() )
			{
				ImmutableMap<String,String> ldapEntry = ldapRecs.next();
				
				if( ldapEntry.get( uidKey ).equals(userIDfromDB) )
				{
					return false;
					
				}//if
				
			}//while
			
		} 
		catch( final LDAPException			  |
					 GeneralSecurityException |
					 SQLException err )
		{
			final CriticalException errWrapped = new CriticalException( err );
			errWrapped.accept( new ErrorLoggingVisitor() );
			
			return true;
			
		}//try

		return true;
		
	}//method

	
}//class
